/**
 * Copyright (c) 2006-2016, JGraph Ltd
 * Copyright (c) 2006-2016, Gaudenz Alder
 */
var mxResources =
{
    /**
     * Class: mxResources
     *
     * Implements internationalization. You can provide any number of
     * resource files on the server using the following format for the
     * filename: name[-en].properties. The en stands for any lowercase
     * 2-character language shortcut (eg. de for german, fr for french).
     *
     * If the optional language extension is omitted, then the file is used as a
     * default resource which is loaded in all cases. If a properties file for a
     * specific language exists, then it is used to override the settings in the
     * default resource. All entries in the file are of the form key=value. The
     * values may then be accessed in code via <get>. Lines without
     * equal signs in the properties files are ignored.
     *
     * Resource files may either be added programmatically using
     * <add> or via a resource tag in the UI section of the
     * editor configuration file, eg:
     *
     * (code)
     * <mxEditor>
     *   <ui>
     *     <resource basename="examples/resources/mxWorkflow"/>
     * (end)
     *
     * The above element will load examples/resources/mxWorkflow.properties as well
     * as the language specific file for the current language, if it exists.
     *
     * Values may contain placeholders of the form {1}...{n} where each placeholder
     * is replaced with the value of the corresponding array element in the params
     * argument passed to <mxResources.get>. The placeholder {1} maps to the first
     * element in the array (at index 0).
     *
     * See <mxClient.language> for more information on specifying the default
     * language or disabling all loading of resources.
     *
     * Lines that start with a # sign will be ignored.
     *
     * Special characters
     *
     * To use unicode characters, use the standard notation (eg. \u8fd1) or %u as a
     * prefix (eg. %u20AC will display a Euro sign). For normal hex encoded strings,
     * use % as a prefix, eg. %F6 will display a "o umlaut" (&ouml;).
     *
     * See <resourcesEncoded> to disable this. If you disable this, make sure that
     * your files are UTF-8 encoded.
     *
     * Asynchronous loading
     *
     * By default, the core adds two resource files synchronously at load time.
     * To load these files asynchronously, set <mxLoadResources> to false
     * before loading mxClient.js and use <mxResources.loadResources> instead.
     *
     * Variable: resources
     *
     * Object that maps from keys to values.
     */
    resources: {},

    /**
     * Variable: extension
     *
     * Specifies the extension used for language files. Default is <mxResourceExtension>.
     */
    extension: mxResourceExtension,

    /**
     * Variable: resourcesEncoded
     *
     * Specifies whether or not values in resource files are encoded with \u or
     * percentage. Default is false.
     */
    resourcesEncoded: false,

    /**
     * Variable: loadDefaultBundle
     *
     * Specifies if the default file for a given basename should be loaded.
     * Default is true.
     */
    loadDefaultBundle: true,

    /**
     * Variable: loadDefaultBundle
     *
     * Specifies if the specific language file file for a given basename should
     * be loaded. Default is true.
     */
    loadSpecialBundle: true,

    /**
     * Function: isLanguageSupported
     *
     * Hook for subclassers to disable support for a given language. This
     * implementation returns true if lan is in <mxClient.languages>.
     *
     * Parameters:
     *
     * lan - The current language.
     */
    isLanguageSupported: function (lan) {
        if (mxClient.languages != null) {
            return mxUtils.indexOf(mxClient.languages, lan) >= 0;
        }

        return true;
    },

    /**
     * Function: getDefaultBundle
     *
     * Hook for subclassers to return the URL for the special bundle. This
     * implementation returns basename + <extension> or null if
     * <loadDefaultBundle> is false.
     *
     * Parameters:
     *
     * basename - The basename for which the file should be loaded.
     * lan - The current language.
     */
    getDefaultBundle: function (basename, lan) {
        if (mxResources.loadDefaultBundle || !mxResources.isLanguageSupported(lan)) {
            return basename + mxResources.extension;
        }
        else {
            return null;
        }
    },

    /**
     * Function: getSpecialBundle
     *
     * Hook for subclassers to return the URL for the special bundle. This
     * implementation returns basename + '_' + lan + <extension> or null if
     * <loadSpecialBundle> is false or lan equals <mxClient.defaultLanguage>.
     *
     * If <mxResources.languages> is not null and <mxClient.language> contains
     * a dash, then this method checks if <isLanguageSupported> returns true
     * for the full language (including the dash). If that returns false the
     * first part of the language (up to the dash) will be tried as an extension.
     *
     * If <mxResources.language> is null then the first part of the language is
     * used to maintain backwards compatibility.
     *
     * Parameters:
     *
     * basename - The basename for which the file should be loaded.
     * lan - The language for which the file should be loaded.
     */
    getSpecialBundle: function (basename, lan) {
        if (mxClient.languages == null || !this.isLanguageSupported(lan)) {
            var dash = lan.indexOf('-');

            if (dash > 0) {
                lan = lan.substring(0, dash);
            }
        }

        if (mxResources.loadSpecialBundle && mxResources.isLanguageSupported(lan) && lan != mxClient.defaultLanguage) {
            return basename + '_' + lan + mxResources.extension;
        }
        else {
            return null;
        }
    },

    /**
     * Function: add
     *
     * Adds the default and current language properties file for the specified
     * basename. Existing keys are overridden as new files are added. If no
     * callback is used then the request is synchronous.
     *
     * Example:
     *
     * At application startup, additional resources may be
     * added using the following code:
     *
     * (code)
     * mxResources.add('resources/editor');
     * (end)
     *
     * Parameters:
     *
     * basename - The basename for which the file should be loaded.
     * lan - The language for which the file should be loaded.
     * callback - Optional callback for asynchronous loading.
     */
    add: function (basename, lan, callback) {
        lan = (lan != null) ? lan : ((mxClient.language != null) ?
            mxClient.language.toLowerCase() : mxConstants.NONE);

        if (lan != mxConstants.NONE) {
            var defaultBundle = mxResources.getDefaultBundle(basename, lan);
            var specialBundle = mxResources.getSpecialBundle(basename, lan);

            var loadSpecialBundle = function () {
                if (specialBundle != null) {
                    if (callback) {
                        mxUtils.get(specialBundle, function (req) {
                            mxResources.parse(req.getText());
                            callback();
                        }, function () {
                            callback();
                        });
                    }
                    else {
                        try {
                            var req = mxUtils.load(specialBundle);

                            if (req.isReady()) {
                                mxResources.parse(req.getText());
                            }
                        }
                        catch (e) {
                            // ignore
                        }
                    }
                }
                else if (callback != null) {
                    callback();
                }
            }

            if (defaultBundle != null) {
                if (callback) {
                    mxUtils.get(defaultBundle, function (req) {
                        mxResources.parse(req.getText());
                        loadSpecialBundle();
                    }, function () {
                        loadSpecialBundle();
                    });
                }
                else {
                    try {
                        var req = mxUtils.load(defaultBundle);

                        if (req.isReady()) {
                            mxResources.parse(req.getText());
                        }

                        loadSpecialBundle();
                    }
                    catch (e) {
                        // ignore
                    }
                }
            }
            else {
                // Overlays the language specific file (_lan-extension)
                loadSpecialBundle();
            }
        }
    },

    /**
     * Function: parse
     *
     * Parses the key, value pairs in the specified
     * text and stores them as local resources.
     */
    parse: function (text) {
        if (text != null) {
            var lines = text.split('\n');

            for (var i = 0; i < lines.length; i++) {
                if (lines[i].charAt(0) != '#') {
                    var index = lines[i].indexOf('=');

                    if (index > 0) {
                        var key = lines[i].substring(0, index);
                        var idx = lines[i].length;

                        if (lines[i].charCodeAt(idx - 1) == 13) {
                            idx--;
                        }

                        var value = lines[i].substring(index + 1, idx);

                        if (this.resourcesEncoded) {
                            value = value.replace(/\\(?=u[a-fA-F\d]{4})/g, "%");
                            mxResources.resources[key] = unescape(value);
                        }
                        else {
                            mxResources.resources[key] = value;
                        }
                    }
                }
            }
        }
    },

    /**
     * Function: get
     *
     * Returns the value for the specified resource key.
     *
     * Example:
     * To read the value for 'welomeMessage', use the following:
     * (code)
     * var result = mxResources.get('welcomeMessage') || '';
     * (end)
     *
     * This would require an entry of the following form in
     * one of the English language resource files:
     * (code)
     * welcomeMessage=Welcome to mxGraph!
     * (end)
     *
     * The part behind the || is the string value to be used if the given
     * resource is not available.
     *
     * Parameters:
     *
     * key - String that represents the key of the resource to be returned.
     * params - Array of the values for the placeholders of the form {1}...{n}
     * to be replaced with in the resulting string.
     * defaultValue - Optional string that specifies the default return value.
     */
    get: function (key, params, defaultValue) {
        var value = mxResources.resources[key];

        // Applies the default value if no resource was found
        if (value == null) {
            value = defaultValue;
        }

        // Replaces the placeholders with the values in the array
        if (value != null && params != null) {
            value = mxResources.replacePlaceholders(value, params);
        }

        return value;
    },

    /**
     * Function: replacePlaceholders
     *
     * Replaces the given placeholders with the given parameters.
     *
     * Parameters:
     *
     * value - String that contains the placeholders.
     * params - Array of the values for the placeholders of the form {1}...{n}
     * to be replaced with in the resulting string.
     */
    replacePlaceholders: function (value, params) {
        var result = [];
        var index = null;

        for (var i = 0; i < value.length; i++) {
            var c = value.charAt(i);

            if (c == '{') {
                index = '';
            }
            else if (index != null && c == '}') {
                index = parseInt(index) - 1;

                if (index >= 0 && index < params.length) {
                    result.push(params[index]);
                }

                index = null;
            }
            else if (index != null) {
                index += c;
            }
            else {
                result.push(c);
            }
        }

        return result.join('');
    },

    /**
     * Function: loadResources
     *
     * Loads all required resources asynchronously. Use this to load the graph and
     * editor resources if <mxLoadResources> is false.
     *
     * Parameters:
     *
     * callback - Callback function for asynchronous loading.
     */
    loadResources: function (callback) {
        mxResources.add(mxClient.basePath + '/resources/editor', null, function () {
            mxResources.add(mxClient.basePath + '/resources/graph', null, callback);
        });
    }
};